package com.ruoyi.common.utils.sql;

import com.alibaba.druid.pool.DruidDataSource;
import com.ruoyi.common.utils.StringTools;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.sql.*;
import java.util.Properties;

@Component
public class DBUtil {

    //环境配置
    private static String env;

    //配置文件名
    private static String fileName = "application-druid.yml";

    // 声明druid连接池对象
    private static DruidDataSource pool = null;

    //数据库 链接URL地址
    private static String url;

    //账号
    private static String username;

    //密码
    private static String password;

    //初始连接数
    private static int initialSize;

    //最大活动连接数
    private static int maxActive;

    //最小闲置连接数
    private static int minIdle;

    //连接耗尽时最大等待获取连接时间
    private static long maxWait;

    //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
    private static long timeBetweenEvictionRunsMillis;

    //配置一个连接在池中最小生存的时间，单位是毫秒
    private static long minEvictableIdleTimeMillis;

    //配置一个连接在池中最大生存的时间，单位是毫秒
    private static long maxEvictableIdleTimeMillis;

    //配置检测连接是否有效
    private static String validationQuery;

    private static boolean testWhileIdle;

    private static boolean testOnBorrow;

    private static boolean testOnReturn;


    static {
        init();
    }

    private static void init() {

        try {

            //获取环境配置
            Resource resource = new ClassPathResource("application.yml");
            YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
            yamlFactory.setResources(resource);
            Properties properties = yamlFactory.getObject();
            String activeProfile = SpringUtils.getActiveProfile();
            env = StringUtils.isEmpty(activeProfile) ? (String) properties.get("spring.profiles.active") : activeProfile;
            System.out.println(env);
            properties.clear();
            if (StringUtils.isNotEmpty(env)) {
                fileName = "application-" + env + ".yml";
            }
            resource = new ClassPathResource(fileName);
            yamlFactory.setResources(resource);
            properties = yamlFactory.getObject();
            url = StringTools.objString(properties.get("spring.datasource.druid.master.url"));
            username = StringTools.objString(properties.get("spring.datasource.druid.master.username"));
            password = StringTools.objString(properties.get("spring.datasource.druid.master.password"));
            initialSize = (int) properties.get("spring.datasource.druid.initialSize");
            maxActive = (int) properties.get("spring.datasource.druid.maxActive");
            minIdle = (int) properties.get("spring.datasource.druid.minIdle");
            maxWait = (int) properties.get("spring.datasource.druid.maxWait");
            timeBetweenEvictionRunsMillis = Long.parseLong(StringTools.objString(properties.get("spring.datasource.druid.timeBetweenEvictionRunsMillis")));
            minEvictableIdleTimeMillis = Long.parseLong(StringTools.objString(properties.get("spring.datasource.druid.minEvictableIdleTimeMillis")));
            maxEvictableIdleTimeMillis = Long.parseLong(StringTools.objString(properties.get("spring.datasource.druid.maxEvictableIdleTimeMillis")));
            validationQuery = StringTools.objString(properties.get("validationQuery"));
            testWhileIdle = StringTools.stringToBoolean(StringTools.objString(properties.get("spring.datasource.druid.testWhileIdle")));
            testOnBorrow = StringTools.stringToBoolean(StringTools.objString(properties.get("spring.datasource.druid.testOnBorrow")));
            testOnReturn = StringTools.stringToBoolean(StringTools.objString(properties.get("spring.datasource.druid.testOnReturn")));

            if (pool == null) {
                pool = new DruidDataSource();
            }
            pool.setUrl(url);
            pool.setUsername(username);
            pool.setPassword(password);
            pool.setInitialSize(initialSize);  // 设置连接池中初始连接数
            pool.setMinIdle(minIdle);  // 设置最小的闲置链接数
            pool.setMaxActive(maxActive);      // 设置最大连接数
            pool.setMaxWait(maxWait); // 设置最大的等待时间(等待获取链接的时间)
            pool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
            pool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);  //配置一个连接在池中最小生存的时间，单位是毫秒
            pool.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); //配置一个连接在池中最大生存的时间，单位是毫秒
            pool.setValidationQuery(validationQuery); //配置检测连接是否有效
            pool.setTestWhileIdle(testWhileIdle);//配置检测连接是否有效
            pool.setTestOnBorrow(testOnBorrow);
            pool.setTestOnReturn(testOnReturn);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 链接获取
     *
     * @return
     */
    public static Connection getConnection() {
        try {
            // 如果连接池为空或者被异常关闭,则重新初始化一个
            if (pool == null || pool.isClosed()) {
                init();
            }
            return pool.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 资源关闭
     *
     * @param stmt
     * @param conn
     */
    public static void closeConnection(Statement stmt, Connection conn) {
        try {
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行增删改操作
     */
    public static int exeUpdate(Connection conn, String sql, Object... obj) {
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < obj.length; i++) {
                ps.setObject(i + 1, obj[i]);
            }
            return ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(ps, null);
        }
        return 0;
    }

    /**
     * 执行查询操作
     */
    public static ResultSet exeQuery(Connection conn, String sql, Object[] obj) {
        ResultSet rs = null;
        PreparedStatement pstmt = null;
        try {
            pstmt = conn.prepareStatement(sql);
            if (obj != null) {
                for (int i = 0; i < obj.length; i++) {
                    pstmt.setObject(i + 1, obj[i]);
                }
            }
            rs = pstmt.executeQuery();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//			closeAll(null,pstmt,null);
        }
        return rs;
    }

    @Value("${spring.profiles.active}")
    public void setEnv(String env) {
        DBUtil.env = env;
    }
}
